package com.ctshk.rpc.system.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctshk.common.constant.SystemConstants;
import com.ctshk.common.dto.Result;
import com.ctshk.common.enums.IsDeletedCode;
import com.ctshk.common.enums.SupplierStatus;
import com.ctshk.common.enums.SystemError;
import com.ctshk.common.enums.UserStatus;
import com.ctshk.common.exception.BusinessException;
import com.ctshk.common.utils.EntityUtil;
import com.ctshk.common.utils.SnowflakeIdWorker;
import com.ctshk.rpc.system.dto.QueryChildrenDeptDTO;
import com.ctshk.rpc.system.dto.SysDepartmentDTO;
import com.ctshk.rpc.system.dto.SysDepartmentEmployeeDTO;
import com.ctshk.rpc.system.dto.UserDTO;
import com.ctshk.rpc.system.entity.SysDepartment;
import com.ctshk.rpc.system.entity.SysUser;
import com.ctshk.rpc.system.mapper.SysDepartmentMapper;
import com.ctshk.rpc.system.mapper.SysUserMapper;
import com.ctshk.rpc.system.req.SysDepartmentReq;
import com.ctshk.rpc.system.service.ISysDepartmentService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 组织架构 服务实现类
 * </p>
 *
 * @author 谢诗宏
 * @since 2020-12-22
 */
@Slf4j
@DubboService
public class SysDepartmentServiceImpl extends ServiceImpl<SysDepartmentMapper, SysDepartment> implements ISysDepartmentService {

    @Autowired
    private SysDepartmentMapper sysDepartmentMapper;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Override
    public int add(SysDepartmentReq sysDepartmentReq, long userId) {
        QueryWrapper<SysDepartment> queryWrapper = new QueryWrapper<SysDepartment>();
        queryWrapper.lambda().eq(SysDepartment::getDeptCode, sysDepartmentReq.getDeptCode());
        List<SysDepartment> list = baseMapper.selectList(queryWrapper);
        if (CollectionUtils.isNotEmpty(list)) {
            throw new BusinessException(SystemError.SYSTEM_2105);
        }
        SysDepartment parentDept = baseMapper.selectOne(new QueryWrapper<SysDepartment>().lambda()
                .eq(SysDepartment::getId, sysDepartmentReq.getParentId()));
        String nextDeptNumber = baseMapper.selectNextDeptNumber(parentDept.getDeptNumber());
        SysDepartment sysDepartment = new SysDepartment();
        BeanUtils.copyProperties(sysDepartmentReq, sysDepartment);
        sysDepartment.setId(SnowflakeIdWorker.nextId());
        sysDepartment.setDeptNumber(nextDeptNumber);
        sysDepartment.setCreateId(userId);
        sysDepartment.setSysCode(SystemConstants.SYSTEM_CODE + RandomUtil.randomNumbers(8));
        return sysDepartmentMapper.insert(sysDepartment);
    }

    @Override
    public int del(long deptId, long userId) {
        SysDepartment sysDepartment = sysDepartmentMapper.selectById(deptId);
        if (sysDepartment == null || sysDepartment.getIsDeleted() == 1) {
            throw new BusinessException(SystemError.SYS_411);
        }

        List<SysDepartment> depts = sysDepartmentMapper.selectList(Wrappers.<SysDepartment>lambdaQuery().eq(SysDepartment::getParentId, deptId).eq(SysDepartment::getIsDeleted, 0));
        List<SysUser> users = sysUserMapper.selectList(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getDeptId, deptId).eq(SysUser::getIsDeleted, 0));
        if (CollUtil.isNotEmpty(depts) || CollUtil.isNotEmpty(users)) {
            throw new BusinessException(SystemError.SYSTEM_2010);
        }
        sysDepartment.setIsDeleted(1);
        sysDepartment.setModifiedId(userId);

        return sysDepartmentMapper.updateById(sysDepartment);
    }

    @Override
    public int update(SysDepartmentReq sysDepartmentReq, long userId) {
        SysDepartment sysDepartment = sysDepartmentMapper.selectById(sysDepartmentReq.getId());
        if (sysDepartment == null || sysDepartment.getIsDeleted() == IsDeletedCode.YES.getCode()) {
            throw new BusinessException(SystemError.SYS_411);
        }
        BeanUtils.copyProperties(sysDepartmentReq, sysDepartment);
        return sysDepartmentMapper.updateById(sysDepartment);
    }

    @Override
    public List<SysDepartmentDTO> query(long deptId, long userId, boolean isAll) {
        List<SysDepartmentDTO> result = new ArrayList<>();
        if (deptId != 0) {
            SysDepartment sysDepartment = sysDepartmentMapper.selectById(deptId);
            if (sysDepartment == null || sysDepartment.getIsDeleted() == IsDeletedCode.YES.getCode()) {
                throw new BusinessException(SystemError.SYS_411);
            }
            BeanUtils.copyProperties(sysDepartment, result);
            return result;
        }

        List<SysDepartment> sysDepartments = sysDepartmentMapper.selectList(
                Wrappers.<SysDepartment>lambdaQuery()
                        .eq(SysDepartment::getIsDeleted, IsDeletedCode.NO.getCode())
                        .eq(!isAll, SysDepartment::getStatus, SupplierStatus.ENABLE.getCode())
        );
//        List<TreeNode<SysDepartment>> nodeList = CollUtil.newArrayList();

        TreeNodeConfig treeNodeConfig = new TreeNodeConfig();
        // 自定义属性名
        // 默认支持排序
        treeNodeConfig.setWeightKey("sort");
        treeNodeConfig.setChildrenKey("children");

        //可配置树深度
        treeNodeConfig.setDeep(3);
        treeNodeConfig.setIdKey("id");

        //转换器
        List<Tree<String>> build = TreeUtil.build(sysDepartments, "0", treeNodeConfig,
                (treeNode, tree) -> {
                    tree.setId(treeNode.getId().toString());
                    tree.setParentId(treeNode.getParentId().toString());
                    // tree.setWeight(treeNode.getOrderNum());
                    tree.setName(treeNode.getTitle());
                    // 扩展属性
                    tree.putExtra("key", treeNode.getId());
                    tree.putExtra("title", treeNode.getTitle());
                    tree.putExtra("sysCode", treeNode.getSysCode());
                    tree.putExtra("deptCode", treeNode.getDeptCode());
                    tree.putExtra("orgType", treeNode.getOrgType());
                    tree.putExtra("status", treeNode.getStatus());
                    tree.putExtra("sort", treeNode.getSort());
                    tree.putExtra("businessTypeId", treeNode.getBusinessTypeId());
                    tree.putExtra("remark", treeNode.getRemark());
                });
/*        List<SysDepartment> deptList = new ArrayList(); // 生成字段部门编号
        itor(deptList, build, 1, "");
        for (SysDepartment sysDepartment : deptList) {
            sysDepartmentMapper.update(null, new UpdateWrapper<SysDepartment>().lambda()
                    .eq(SysDepartment::getId, sysDepartment.getId())
                    .set(SysDepartment::getDeptNumber, sysDepartment.getDeptNumber()));
        }*/
        result = JSONArray.parseArray(JSONObject.toJSONString(build), SysDepartmentDTO.class);
        return result;
    }

    private void itor(List<SysDepartment> deptList, List<Tree<String>> build, int level, String code) {
        for (int i = 0; i < build.size(); i++) {
            Tree<String> tree = build.get(i);
            String codeTemp = null;
            if (level == 1) {
                codeTemp = code + (i + 1);
                System.out.println("dept code:" + codeTemp + ",name:" + tree.getName());
            } else if (level >= 2) {
                codeTemp = code + StringUtils.leftPad(String.valueOf(i + 1), 3, "0");
                System.out.println("dept code:" + codeTemp + ",name:" + tree.getName());
            }
            SysDepartment sysDepartment = new SysDepartment();
            sysDepartment.setId(Long.valueOf(tree.getId()));
            sysDepartment.setDeptNumber(codeTemp);
            deptList.add(sysDepartment);
            if (null != tree.getChildren()) {
                itor(deptList, tree.getChildren(), level + 1, codeTemp);
            }
        }
    }

    @Override
    public void setStatus(long deptId, int status, long userId) {
        List<SysDepartment> sysMenus = sysDepartmentMapper.selectChildren(deptId);
        if (status == 1) {
            sysMenus.addAll(sysDepartmentMapper.selectParents(deptId));
        } else if (status == 0) {
            sysMenus.add(sysDepartmentMapper.selectById(deptId));
        }
        sysMenus.forEach(sysMenu -> {
            sysMenu.setStatus(status);
            sysMenu.setModifiedId(userId);
            sysDepartmentMapper.updateById(sysMenu);
        });
    }

    @Override
    public List<SysDepartmentEmployeeDTO> queryDeptEmployees(String searchName, String type) {
        List<SysDepartmentEmployeeDTO> result;

        // 查询所有组织部门架构
        List<SysDepartment> sysMenus = sysDepartmentMapper.selectList(Wrappers.<SysDepartment>lambdaQuery()
                .like(StringUtils.isNotBlank(searchName), SysDepartment::getTitle, searchName)
                .eq(SysDepartment::getStatus, SupplierStatus.ENABLE.getCode())
                .eq(SysDepartment::getIsDeleted, IsDeletedCode.NO.getCode()));

        TreeNodeConfig treeNodeConfig = new TreeNodeConfig();
        // 自定义属性名
        // 默认支持排序
        treeNodeConfig.setWeightKey("sort");
        treeNodeConfig.setChildrenKey("children");

        //可配置树深度
        treeNodeConfig.setDeep(3);
        treeNodeConfig.setIdKey("id");

        //转换器
        List<Tree<String>> build = TreeUtil.build(sysMenus, "0", treeNodeConfig,
                (treeNode, tree) -> {
                    tree.setId(treeNode.getId().toString());
                    tree.setParentId(treeNode.getParentId().toString());
                    tree.setName(treeNode.getTitle());

                    // 扩展属性
                    tree.putExtra("key", treeNode.getId());
                    tree.putExtra("title", treeNode.getTitle());
                    tree.putExtra("sysCode", treeNode.getSysCode());
                    tree.putExtra("sort", treeNode.getSort());
                    if (StringUtils.equals(type, "all")) {
                        List<SysUser> sysUsers = sysUserMapper.selectList(Wrappers.<SysUser>lambdaQuery()
                                .eq(SysUser::getDeptId, treeNode.getId())
                                .eq(SysUser::getStatus, 1)
                                .eq(SysUser::getIsDeleted, 0));
                        tree.putExtra("employees", EntityUtil.copyList(sysUsers, UserDTO.class));
                    }
                });

        result = JSONArray.parseArray(JSONObject.toJSONString(build), SysDepartmentEmployeeDTO.class);
        return result;
    }

    @Override
    public SysDepartmentDTO queryOne(long deptId) {
        SysDepartment sysDepartment = sysDepartmentMapper.selectById(deptId);
        return EntityUtil.copy(sysDepartment, SysDepartmentDTO.class);
    }

    @Override
    public SysDepartmentDTO queryByUserId(long userId) {
        SysUser user = sysUserMapper.selectById(userId);
        if (user == null) {
            return new SysDepartmentDTO();
        }
        SysDepartment sysDepartment = sysDepartmentMapper.selectById(user.getDeptId());
        return EntityUtil.copy(sysDepartment, SysDepartmentDTO.class);
    }

    @Override
    public List<Long> queryIdsByUserId(long userId) {
        SysUser user = sysUserMapper.selectById(userId);
        if (user == null) {
            return Collections.emptyList();
        }
        List<Long> ids = new ArrayList<>();
        ids.addAll(sysDepartmentMapper.selectParentIds(user.getDeptId()));
        return ids;
    }

    @Override
    public List<Long> queryIdsById(long deptId) {
        List<Long> ids = new ArrayList<>();
        ids.addAll(sysDepartmentMapper.selectParentIds(deptId));
        return ids;
    }

    @Override
    public boolean isExist(long deptId, long userId) {
        if (deptId == 0 || userId == 0) {
            return false;
        }
        List<Long> childrenIds = sysDepartmentMapper.selectChildrenIds(deptId);
        childrenIds.add(deptId);

        List<SysUser> users = sysUserMapper.selectList(Wrappers.<SysUser>lambdaQuery()
                .in(SysUser::getDeptId, childrenIds)
                .eq(SysUser::getStatus, 1)
                .eq(SysUser::getIsDeleted, 0));

        return users.stream().filter(user -> user.getId() == userId).findAny().isPresent();
    }

    @Override
    public boolean isExists(List<Long> deptIds, long userId) {
        if (CollUtil.isEmpty(deptIds) || userId == 0) {
            return false;
        }
        boolean isExist = false;
        for (long deptId : deptIds) {
            List<Long> childrenIds = sysDepartmentMapper.selectChildrenIds(deptId);
            childrenIds.add(deptId);

            List<SysUser> users = sysUserMapper.selectList(Wrappers.<SysUser>lambdaQuery()
                    .in(SysUser::getDeptId, childrenIds)
                    .eq(SysUser::getStatus, 1)
                    .eq(SysUser::getIsDeleted, 0));
            isExist = users.stream().filter(user -> user.getId() == userId).findAny().isPresent();
            if (isExist) {
                break;
            }
        }
        return isExist;
    }

    @Override
    public List<Long> queryCUserIdsByDeptId(long deptId) {
        List<Long> ids = new ArrayList<>();
        ids.add(deptId);
        List<Long> userIds = sysUserMapper.selectObjs(Wrappers.<SysUser>lambdaQuery().select(SysUser::getId)
                .eq(SysUser::getDeptId, deptId)).stream().map(o -> (Long) o).collect(Collectors.toList());
        ids.addAll(userIds);
        return userIds;
    }

    @Override
    public List<Long> queryCUserIdsByDeptIdEffective(long deptId) {
        List<Long> ids = new ArrayList<>();
        ids.add(deptId);
        List<Long> userIds = sysUserMapper.selectObjs(Wrappers.<SysUser>lambdaQuery()
                .select(SysUser::getId)
                .eq(SysUser::getDeptId, deptId)
                .eq(SysUser::getStatus, UserStatus.ENABLE)
                .eq(SysUser::getIsDeleted,IsDeletedCode.NO.getCode())
        ).stream().map(o -> (Long) o).collect(Collectors.toList());
        ids.addAll(userIds);
        return userIds;
    }

    @Override
    public List<Long> queryUserIdsByDeptId(long deptId) {
        List<Long> userIds = new ArrayList<>();
        List<Long> childrenIds = new ArrayList<>();
        childrenIds.add(deptId);
        childrenIds.addAll(sysDepartmentMapper.selectChildrenIds(deptId));
        List<Long> uIds = sysUserMapper.selectObjs(Wrappers.<SysUser>lambdaQuery().select(SysUser::getId)
                .in(SysUser::getDeptId, childrenIds)).stream().map(o -> (Long) o).collect(Collectors.toList());
        userIds.addAll(uIds);
        return userIds;
    }

    @Override
    public Result<List<QueryChildrenDeptDTO>> queryChildrenDept() {
        Long departmentId = 7876848247635968L;//香港中國旅行社有限公司

        QueryWrapper<SysDepartment> queryWrapper = new QueryWrapper<SysDepartment>();
        queryWrapper.lambda().eq(SysDepartment::getParentId, departmentId);
        queryWrapper.lambda().eq(SysDepartment::getIsDeleted, IsDeletedCode.NO.getCode());
        List<SysDepartment> list = baseMapper.selectList(queryWrapper);
        List<QueryChildrenDeptDTO> resultList = EntityUtil.copyList(list, QueryChildrenDeptDTO.class);
        return Result.success(resultList);
    }

}
